package middleware

import (
	"context"
	"net/http"
	"net/url"
	"strconv"

	"gitee.com/kessil/chicory/internal/utils"
)

const (
	QueryFilterKey contextKey = "queryFilter"
)

// QueryFilter 查询过滤器
type QueryFilter struct {
	Filters map[string]interface{}
}

// QueryMiddleware 查询中间件
func QueryMiddleware(allowedFields []string) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			filters := parseQueryFilters(r.URL.Query(), allowedFields)
			utils.Printf(filters)
			queryFilter := QueryFilter{
				Filters: filters,
			}

			// 存入上下文
			ctx := context.WithValue(r.Context(), QueryFilterKey, queryFilter)
			next.ServeHTTP(w, r.WithContext(ctx))
		})
	}
}

// parseQueryFilters 解析查询参数为过滤器
func parseQueryFilters(query url.Values, allowedFields []string) map[string]interface{} {
	filters := make(map[string]interface{})

	for key, values := range query {
		// 跳过系统参数
		if isSystemParam(key) {
			continue
		}

		// 检查字段是否允许
		if len(allowedFields) > 0 && !isFieldAllowed(key, allowedFields) {
			continue
		}

		if len(values) > 0 && values[0] != "" {
			value := values[0]

			// 尝试转换数字类型
			if intValue, err := strconv.Atoi(value); err == nil {
				filters[key] = intValue
			} else if boolValue, err := strconv.ParseBool(value); err == nil {
				filters[key] = boolValue
			} else {
				filters[key] = value
			}
		}
	}

	return filters
}

func isSystemParam(key string) bool {
	systemParams := map[string]bool{
		"pageNo":   true,
		"pageSize": true,
		"sort":     true,
		"order":    true,
	}
	return systemParams[key]
}

func isFieldAllowed(field string, allowedFields []string) bool {
	if len(allowedFields) == 0 {
		return true
	}

	for _, allowed := range allowedFields {
		if field == allowed {
			return true
		}
	}
	return false
}

// GetQueryFiltersFromContext 从上下文中获取查询过滤器
func GetQueryFiltersFromContext(r *http.Request) map[string]interface{} {
	if queryFilter, ok := r.Context().Value(QueryFilterKey).(QueryFilter); ok {
		return queryFilter.Filters
	}
	return nil
}
